/**    
 * 文件名：AuthCodeApprovalHandler.java</br>
 *    
 * 版本信息：v1.0</br>
 * 日期：2017年10月13日</br>
 * © 2005-2017 雷技信息科技（上海）有限公司版权所有</br>
 *
 */
package com.logic.landseaserver.models.approval.taskhandle;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.logic.system.service.IConfigurationService;
import com.logic.system.service.impl.ConfigurationService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.logic.common.security.SecurityUtils;
import com.logic.landseaserver.common.LandeaConstants.AppropriateType;
import com.logic.landseaserver.common.LandeaConstants.ApprovalStatus;
import com.logic.landseaserver.common.LandeaConstants.CodeType;
import com.logic.landseaserver.common.LandeaConstants.CouponStatus;
import com.logic.landseaserver.common.LandeaConstants.FeeType;
import com.logic.landseaserver.common.LandeaConstants.TaskType;
import com.logic.landseaserver.common.config.ScheduleConfiguration;
import com.logic.landseaserver.common.config.SendMsgConfiguration;
import com.logic.landseaserver.common.enums.BillTypeEnum;
import com.logic.landseaserver.common.exception.LandseaException;
import com.logic.landseaserver.common.exception.ResultCodes.ApprovalResultCode;
import com.logic.landseaserver.common.util.ConstantChar;
import com.logic.landseaserver.common.util.SMSUtil;
import com.logic.landseaserver.common.util.StringTools;
import com.logic.landseaserver.domain.ApprovalRecord;
import com.logic.landseaserver.domain.ApprovalTempRecord;
import com.logic.landseaserver.domain.Coupon;
import com.logic.landseaserver.models.approval.bean.ApprovalCheckResult;
import com.logic.landseaserver.models.approval.bean.ApprovalReq;
import com.logic.landseaserver.models.approval.bean.SubmitApprovalReq;
import com.logic.landseaserver.persistence.read.CouponReadMapper;
import com.logic.landseaserver.persistence.write.CouponWriteMapper;
import com.logic.landseaserver.ws.dto.PersonInfoDTO;
import com.logic.system.persistence.read.UserReadMapper;

/**
 *
 * 项目名称：system-server</br>
 * 类名称：AuthCodeApprovalHandler</br>
 * 类描述：</br>
 * 创建人：Aaron</br>
 * 创建时间：2017年10月13日 下午3:51:46</br>
 * 
 * @version 1.0
 *
 */
@Service(TaskType.AUTH_CODE + AbractApprovalHandler.BEANID)
public class AuthCodeApprovalHandler extends AbractApprovalHandler
{
    private static final Logger LOGGER = LoggerFactory.getLogger(AuthCodeApprovalHandler.class);
    
    @Autowired
    private CouponReadMapper couponReadMapper;
    
    @Autowired
    private CouponWriteMapper couponWriteMapper;
    
    @Autowired
    private UserReadMapper userReadMapper;
    
    @Autowired
    private SendMsgConfiguration sendMsgConfiguration;
    
    @Autowired
    private ScheduleConfiguration scheduleConfig;

    @Autowired
    private IConfigurationService configurationService;
    
    /**
     * [描述]：</br>
     *
     * @param submitApprovalReq
     * @throws LandseaException
     *
     */
    @Override
    protected void submitCheckCustom(SubmitApprovalReq submitApprovalReq, ApprovalCheckResult checkResult)
        throws LandseaException
    {
        Integer taskId = submitApprovalReq.getTaskId();
        // 校验实体是否存在
        Coupon coupon = couponReadMapper.selectByPrimaryKey(taskId);
        if (null == coupon || coupon.getDeleted())
        {
            throw LandseaException.createException(ApprovalResultCode.E00640002);
        }
        
        // 只有草稿状态的授权码才可以提交审核
        if (!CouponStatus.DRAFT.equals(coupon.getStatus()))
        {
            throw LandseaException.createException(ApprovalResultCode.E00650012);
        }
        
        checkResult.setObject(coupon);
    }
    
    /**
     * [描述]：</br>
     * @param checkResult
     * @throws LandseaException
     *
     */
    @Override
    public void submitCustom(ApprovalRecord approvalRecord, ApprovalCheckResult checkResult)
        throws LandseaException
    {
        try
        {
            // 修改授权码表
            Coupon update = new Coupon();
            update.setId(approvalRecord.getTaskId());
            update.setCreatedBy(null);
            update.setCreatedDtm(null);
            update.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
            // 状态审批中
            update.setStatus(CouponStatus.APPLICATION);
            update.setApprovalStatus(approvalRecord.getApproveStatus());
            
            couponWriteMapper.updateByPrimaryKeySelective(update);
            
            Coupon coupon = (Coupon)checkResult.getObject();
            
            List<Integer> projectIdList = new ArrayList<Integer>();
            List<String> areaList = new ArrayList<String>();
            setProjectIdsAreaIds(projectIdList, areaList, coupon);
            
            ApprovalTempRecord approvalTempRecord = checkResult.getNextApprovalTempRecord();
            // 查询发送给..
            LOGGER.info("submitCustom|发送短信给下一个节点审核人,可审核角色代码" + approvalTempRecord.getApproveRoleCode());
            List<PersonInfoDTO> persionList = queryUserByRoleAndAuth(approvalTempRecord.getApproveRoleCode(), projectIdList, areaList);
            
            if (CollectionUtils.isEmpty(persionList))
            {
                return;
            }
            LOGGER.info("sendSmsToApprovalUser|发送给" + persionList);
            sendApprovalSms(persionList, coupon.getApplicationCode());
        }
        catch (Exception e)
        {
            LOGGER.error("processCustom|授权码提交审核失败." + approvalRecord.toString(), e);
            throw LandseaException.createException(ApprovalResultCode.E00650004, e);
        }
    }
    
    /**
     * [描述]：</br>
     *
     * @param approvalReq
     * @param checkResult
     * @throws LandseaException
     *
     */
    @Override
    protected void approvalCheckCustom(ApprovalReq approvalReq, ApprovalCheckResult checkResult)
        throws LandseaException
    {
        Integer taskId = approvalReq.getTaskId();
        // 校验实体是否存在
        Coupon coupon = couponReadMapper.selectByPrimaryKey(taskId);
        if (null == coupon || coupon.getDeleted())
        {
            throw LandseaException.createException(ApprovalResultCode.E00640002);
        }
        
        checkResult.setObject(coupon);
    }
    
    /**
     * [描述]：</br>
     *
     * @param approvalReq
     * @param checkResult
     * @throws LandseaException
     *
     */
    @Override
    public void approvalCustom(ApprovalReq approvalReq, ApprovalCheckResult checkResult)
        throws LandseaException
    {
        // 更新授权码表审核状态
        try
        {
            ApprovalRecord approvalRecord = checkResult.getCurrentApprovalRecord();
            Coupon coupon = (Coupon)checkResult.getObject();
            String approvalStatus = approvalRecord.getApproveStatus();
            
            // 修改授权码表
            Coupon update = new Coupon();
            update.setId(approvalReq.getTaskId());
            update.setCreatedBy(null);
            update.setCreatedDtm(null);
            update.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
            
            String authCode = null;
            
            // 如果是个人，且审批通过，状态修改为 未使用
            if (AppropriateType.PERSION.equals(coupon.getAppropriateType())
                && ApprovalStatus.APASS.equals(approvalStatus))
            {
                update.setStatus(CouponStatus.UNUSED);
                // 个人审批通过生成授权码
                authCode = generateGRAuthCode(coupon);
            }
            // 如果是通用，且审批通过，状态修改为 未投放
            else if (AppropriateType.COMMON.equals(coupon.getAppropriateType())
                && ApprovalStatus.APASS.equals(approvalStatus))
            {
                update.setStatus(CouponStatus.NOTPUTON);
                // 通用审批通过生成授权码
                authCode = generateTYAuthCode(coupon);
            }
            else if (ApprovalStatus.AREFUSED.equals(approvalStatus))
            {
                // 审批拒绝，授权码状态改成草稿
                update.setStatus(CouponStatus.DRAFT);
            }
            
            update.setAuthCode(authCode);
            update.setApprovalStatus(approvalStatus);
            couponWriteMapper.updateByPrimaryKeySelective(update);
            
            sendSmsToApprovalUser(approvalRecord, checkResult);
        }
        catch (Exception e)
        {
            LOGGER.error("approvalCustom|授权码审核失败." + approvalReq.toString(), e);
            throw LandseaException.createException(ApprovalResultCode.E00650009, e);
        }
    }
    
    private String generateGRAuthCode(Coupon coupon)
    {
        Integer maxAUCode = couponReadMapper.getMaxAuthCode();
        String authCode = null;
        // 优惠类
        if (CodeType.OFFERTYPE.equals(coupon.getCodeType()))
        {
            // 按签约创建生成服务费和月租金
            if (FeeType.FEECREATED.equals(coupon.getFeeType()))
            {
                // 房租
                if (BillTypeEnum.CTBI8.getCode().equals(coupon.getAuthFee()))
                {
                    authCode = generateAUNo("DR", maxAUCode);
                }
                // 服务费
                else if (BillTypeEnum.CTBI9.getCode().equals(coupon.getAuthFee()))
                {
                    authCode = generateAUNo("DF", maxAUCode);
                }
                //定金
                else if (BillTypeEnum.CTBI18.getCode().equals(coupon.getAuthFee()))
                {
                    authCode = generateAUNo("DD", maxAUCode);
                }
                //房屋押金
                else if (BillTypeEnum.CTBI11.getCode().equals(coupon.getAuthFee()))
                {
                    authCode = generateAUNo("DH", maxAUCode);
                }
                //水费押金
                else if (BillTypeEnum.CTBI10.getCode().equals(coupon.getAuthFee()))
                {
                    authCode = generateAUNo("DS", maxAUCode);
                }
            }
            // 按照月结账单创建的DM
            else if (FeeType.MONTHLYBILLCREATED.equals(coupon.getFeeType()))
            {
                authCode = generateAUNo("DM", maxAUCode);
            }
        }
        // 退转换续类
        if (CodeType.RELIEFTYPE.equals(coupon.getCodeType()))
        {
            //滞纳金
            if (BillTypeEnum.CTBI13.getCode().equals(coupon.getAuthFee()))
            {
                authCode = generateAUNo("RL", maxAUCode);
            }
            //违约金
            else if (BillTypeEnum.CTBI14.getCode().equals(coupon.getAuthFee()))
            {
                authCode = generateAUNo("RW", maxAUCode);
            }
            //赔偿金
            else if (BillTypeEnum.CTBI19.getCode().equals(coupon.getAuthFee()))
            {
                authCode = generateAUNo("RP", maxAUCode);
            }
            //转房费
            else if (BillTypeEnum.CTBI20.getCode().equals(coupon.getAuthFee()))
            {
                authCode = generateAUNo("RZ", maxAUCode);
            }
            //换房费
            else if (BillTypeEnum.CTBI21.getCode().equals(coupon.getAuthFee()))
            {
                authCode = generateAUNo("RH", maxAUCode);
            }
            else 
            {
                authCode = generateAUNo("RM", maxAUCode);
            }
        }
        return authCode;
    }
    
    private String generateAUNo(String code, Integer maxAUCode)
    {
        String AUSn = code + new DecimalFormat("00000000").format(maxAUCode);
        return AUSn;
    }
    
    private String generateTYAuthCode(Coupon coupon)
    {
        Integer maxAUCode = couponReadMapper.getMaxAuthCode();
        String authCode = null;
        // 按费项创建生成服务费和月租金
        if (FeeType.FEECREATED.equals(coupon.getFeeType()))
        {
            // 月租金
            if (BillTypeEnum.CTBI8.getCode().equals(coupon.getAuthFee()))
            {
                authCode = generateAUNo("GR", maxAUCode);
            }
            // 服务费
            else if (BillTypeEnum.CTBI9.getCode().equals(coupon.getAuthFee()))
            {
                authCode = generateAUNo("GF", maxAUCode);
            }
            //定金
            else if (BillTypeEnum.CTBI18.getCode().equals(coupon.getAuthFee()))
            {
                authCode = generateAUNo("GD", maxAUCode);
            }
            //房屋押金
            else if (BillTypeEnum.CTBI11.getCode().equals(coupon.getAuthFee()))
            {
                authCode = generateAUNo("GH", maxAUCode);
            }
            //水费押金
            else if (BillTypeEnum.CTBI10.getCode().equals(coupon.getAuthFee()))
            {
                authCode = generateAUNo("GS", maxAUCode);
            }
        }
        // 按照月结账单创建的GM
        else if (FeeType.MONTHLYBILLCREATED.equals(coupon.getFeeType()))
        {
            authCode = generateAUNo("GM", maxAUCode);
        }
        return authCode;
    }
    
    /**
     * 
     * [简要描述]：发送给下一个节点要审核的人</br>
     * [详细描述]：</br>
     * [作者]：Aaron(2017-10-17)</br>
     *
     * @param approvalRecord 审核对象
     * @param checkResult
     *
     */
    private void sendSmsToApprovalUser(ApprovalRecord approvalRecord, ApprovalCheckResult checkResult)
    {
        try
        {
            // 下一个节点审核角色
            ApprovalTempRecord nextTemp = checkResult.getNextApprovalTempRecord();
            String roleCode = nextTemp.getApproveRoleCode();
            
            LOGGER.info("sendSmsToApprovalUser|开始发送短信给下一个节点审核人.审核ID:" + approvalRecord.getId() + ",可审核角色代码" + roleCode);
            String approvalStatus = approvalRecord.getApproveStatus();
            // 如果不是审批通过、拒绝，则要发送短信给下一个节点
            if (ApprovalStatus.APASS.equals(approvalStatus) || ApprovalStatus.AREFUSED.equals(approvalStatus))
            {
                LOGGER.info("sendSmsToApprovalUser|状态为审核通过或拒绝，无需发送短信");
                return;
            }
            
            // 查询roleCode角色对应的人员有权限审核该授权码的人员
            Coupon coupon = (Coupon)checkResult.getObject();
            if (null == coupon)
            {
                LOGGER.error("sendSmsToApprovalUser|授权码不存在.");
            }
            
            List<Integer> projectIdList = new ArrayList<Integer>();
            List<String> areaList = new ArrayList<String>();
            setProjectIdsAreaIds(projectIdList, areaList, coupon);
            
            // 查询发送给..
            List<PersonInfoDTO> persionList = queryUserByRoleAndAuth(roleCode, projectIdList, areaList);
            
            if (CollectionUtils.isEmpty(persionList))
            {
                return;
            }
            LOGGER.info("sendSmsToApprovalUser|发送给" + persionList);
            
            sendApprovalSms(persionList, coupon.getApplicationCode());
        }
        catch (Exception e)
        {
            LOGGER.error("sendSmsToApprovalUser|审批授权码发送短信失败.", e);
        }
    }
    
    public List<PersonInfoDTO> queryUserByRoleAndAuth(String roleCode, List<Integer> projectIdList,
        List<String> areaCodeList)
    {
        // 项目条件
        String projectIdsCondition = StringTools.packageAndInSqlbyListInt(" and sup.prj_id ", projectIdList);
        
        // 区域条件
        String areasCondition = StringTools.packageAndInSqlbyListStr(" and sua.area_code ", areaCodeList);
        
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("projectIdsCondition", projectIdsCondition);
        paramMap.put("areasCondition", areasCondition);
        paramMap.put("roleCode", roleCode);
        
        // 要同时过滤掉被暂停的用户、删除的用户
        List<PersonInfoDTO> persionList = userReadMapper.getApprovalAuthPersionInfo(paramMap);
        
        return persionList;
    }
    
    public void sendApprovalSms(List<PersonInfoDTO> pinfoList, String couponCode)
    {
        // 生产环境才发短信
        String cuteEnv = scheduleConfig.getCuteEnv();
        if (ConstantChar.PRD_ENV.equals(cuteEnv))
        {
            String smsCode = sendMsgConfiguration.getAuthCodeApprovalCode();
            for (PersonInfoDTO person : pinfoList)
            {
                String msg = " {'code':'" + couponCode + "'}";
                String signName = configurationService.getStringValue(ConfigurationService.SEND_MSG_SIGN_NAME);
                SMSUtil.sendSms(smsCode, person.getPhone(), msg,signName);
            }
        }
    }
    
    private void setProjectIdsAreaIds(List<Integer> projectIdList,List<String> areaList, Coupon coupon)
    {
        String projectIds = coupon.getProjectIds();
        if (StringUtils.isNotEmpty(projectIds))
        {
            String[] projectIdArr = projectIds.split(",");
            for (String projectId : projectIdArr)
            {
                projectIdList.add(Integer.parseInt(projectId));
            }
        }
        String areas = coupon.getAreaIds();
        if (StringUtils.isNotEmpty(areas))
        {
            String[] areasArr = areas.split(",");
            for (String area : areasArr)
            {
                areaList.add(area);
            }
        }
    }
}
